/*
 * CategoryClassificationDoubleCheck is a software package that uses 
 * data mining to verify that descriptions of items are classified 
 * into the correct categories.
 * 
 * Copyright (C) 2011  CommuniPatient, LLC
 * 
 * File: Item.java
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *  
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.unitvectory.categoryclassification;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

/**
 * The information related to a single item.
 * 
 * @author Jared Hatfield
 * 
 */
public class Item {

	/**
	 * The item identifier.
	 */
	private String id;

	/**
	 * The item name.
	 */
	private String name;

	/**
	 * The item description.
	 */
	private String description;

	/**
	 * The item categories.
	 */
	private List<Category> categories;

	/**
	 * The filtered text composed of the name and description.
	 */
	private String filteredText;

	/**
	 * Initializes a new instance of the Item class.
	 * 
	 * @param id
	 *            The identifier.
	 * @param name
	 *            The name.
	 * @param description
	 *            The description.
	 */
	public Item(String id, String name, String description) {
		this.id = id;
		this.name = name;
		this.description = description;
		this.categories = new ArrayList<Category>();
		this.filteredText = null;
	}

	/**
	 * Gets the identifier.
	 * 
	 * @return The identifier.
	 */
	public String getId() {
		return id;
	}

	/**
	 * Gets the name.
	 * 
	 * @return The name.
	 */
	public String getName() {
		return name;
	}

	/**
	 * Gets the description.
	 * 
	 * @return The description.
	 */
	public String getDescription() {
		return description;
	}

	/**
	 * Gets the list of categories.
	 * 
	 * @return The category list.
	 */
	public List<Category> getCategories() {
		return categories;
	}

	/**
	 * Gets the filtered name and description for the item. The content will be
	 * converted to lower case and all special and numeric characters will be
	 * removed. All stop words will be removed based off of the provided list.
	 * 
	 * <br />
	 * <br />
	 * <b>Note:</b> The result of this function will be cached after the first
	 * call for performance. The first list of stop words passed to the object
	 * will be used and the results will be saved.
	 * 
	 * @param stopWords
	 *            The list of stop words.
	 * @return The filtered text.
	 */
	public String getFilteredString(List<String> stopWords) {
		if (this.filteredText == null) {
			String body = this.getName() + this.getDescription();

			// To lower remove all non alphabetic characters and spaces
			body = body.toLowerCase();
			body = body.replaceAll("[^a-z ]", "");

			// Remove all of the stop words
			StringTokenizer st = new StringTokenizer(body);
			StringBuilder sb = new StringBuilder();
			while (st.hasMoreTokens()) {
				String token = st.nextToken();
				if (!stopWords.contains(token)) {
					sb.append(token).append(" ");
				}
			}

			// Cache the result locally
			this.filteredText = sb.toString();
		}

		return this.filteredText;
	}

	/**
	 * Tests if the item is in a specified category.
	 * 
	 * @param id
	 *            The category id.
	 * @return True item belongs to category; otherwise false.
	 */
	public boolean isInCategory(String id) {
		for (int i = 0; i < this.categories.size(); i++) {
			Category cat = this.categories.get(i);
			if (cat.getId().equals(id)) {
				return true;
			}
		}

		return false;
	}
}
